﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Hallenberg.SmartClient.IO;
using Hallenberg.SmartClient.Interfaces;
using System.IO;
using System.Xml.Serialization;
using Hallenberg.SmartClient.TestModule.Infrastructure;
using Hallenberg.SmartClient.TypeHandlers;
using NUnit.Framework;

namespace Hallenberg.SmartClient.Test.IO
{
    [TestFixture]
    public class ModuleLoaderTest
    {
        [Test]
        public void SmartClient_IO_ModuleLoader_AutoLoadModules_PassNullParam1_ExpectFail()
        {
            WorkItemController workItemController = new WorkItemController();

            ArgumentNullException exception = Assert.Throws<ArgumentNullException>(() =>
                workItemController.ModuleLoader.AutoLoadModules(null, new string[] { "Hallenberg" }));

            Assert.That(exception, Is.Not.Null);
            Assert.That(exception.ParamName, Is.EqualTo("application"));
        }

        [Test]
        public void SmartClient_IO_ModuleLoader_AutoLoadModules_PassNullParam2_ExpectFail()
        {
            ISmartClientApplication smartWareApp = new BaseSmartClientApplication();
            WorkItemController workItemController = new WorkItemController();

            ArgumentNullException exception = Assert.Throws<ArgumentNullException>(() =>
                workItemController.ModuleLoader.AutoLoadModules(smartWareApp, null));

            Assert.That(exception, Is.Not.Null);
            Assert.That(exception.ParamName, Is.EqualTo("startsWith"));
        }

        [Test]
        public void SmartClient_IO_ModuleLoader_LoadModules_PassNullParam1_ExpectFail()
        {
            WorkItemController workItemController = new WorkItemController();
            ArgumentNullException exception = Assert.Throws<ArgumentNullException>(() =>
                workItemController.ModuleLoader.LoadModules(null, "somepath"));

            Assert.That(exception, Is.Not.Null);
            Assert.That(exception.ParamName, Is.EqualTo("application"));
        }

        [Test]
        public void SmartClient_IO_ModuleLoader_LoadModules_PassNullParam2_ExpectFail()
        {
            WorkItemController workItemController = new WorkItemController();
            ISmartClientApplication smartWareApp = new BaseSmartClientApplication();

            ArgumentNullException exception = Assert.Throws<ArgumentNullException>(()=>workItemController.ModuleLoader.LoadModules(smartWareApp, null));

            Assert.That(exception, Is.Not.Null);
            Assert.That(exception.ParamName, Is.EqualTo("configFilePath"));
        }

        [Test]
        public void SmartClient_IO_ModuleLoader_LoadModules_From_File()
        {
            ISmartClientApplication smartWareApp = new BaseSmartClientApplication();

            string configFilePath = Path.Combine(Path.GetTempPath(), string.Format("ModuleConfig_{0}.xml", DateTime.Now.Ticks));
            string moduleFilePath = Path.Combine(Path.GetTempPath(), string.Format("MyModule{0}.dll", DateTime.Now.Ticks));

#if DEBUG
            string sourceModule = Path.Combine(Directory.GetCurrentDirectory(), @"..\..\..\Hallenberg.SmartClient.TestModule\bin\debug\Hallenberg.SmartClient.TestModule.dll");
#else
            string sourceModule = Path.Combine(Directory.GetCurrentDirectory(), @"..\..\..\Hallenberg.SmartClient.TestModule\bin\release\Hallenberg.SmartClient.TestModule.dll");
#endif

            File.Copy(sourceModule, moduleFilePath);

            ModuleDefinition moduleDefinition = new ModuleDefinition()
            {
                FilePath = moduleFilePath,
                ModuleName = "Sample Module"
            };

            ModuleDefinitionCollection moduleDefinitions = new ModuleDefinitionCollection();
            moduleDefinitions.Add(moduleDefinition);

            using (TextWriter tw = File.CreateText(configFilePath))
            {
                XmlSerializer serializer = new XmlSerializer(typeof(ModuleDefinitionCollection));
                serializer.Serialize(tw, moduleDefinitions);
                tw.Flush();
            }

            smartWareApp.WorkItem.ModuleLoader.LoadModules(smartWareApp, configFilePath);
            smartWareApp.WorkItem.Services.RegisterType<IClassTypeHandler, BaseModuleHandler>("Module Handler");

            smartWareApp.ApplicationStart();

            IContactDataLayer contactDataLayer = smartWareApp.WorkItem.Services.Resolve<IContactDataLayer>();

            Assert.That(contactDataLayer, Is.Not.Null);
        }

        [Test]
        public void SmartClient_IO_ModuleLoader_LoadModules_From_File_OmitFilePath_ExpectFail()
        {
            ISmartClientApplication smartWareApp = new BaseSmartClientApplication();
            string configFilePath = Path.Combine(Path.GetTempPath(), String.Format("ModuleConfig_{0}.xml", DateTime.Now.Ticks));

            ModuleDefinition moduleDefinition = new ModuleDefinition()
            {
                FilePath = string.Empty,
                ModuleName = "Sample Module"
            };

            ModuleDefinitionCollection moduleDefinitions = new ModuleDefinitionCollection();
            moduleDefinitions.Add(moduleDefinition);

            using (TextWriter tw = File.CreateText(configFilePath))
            {
                XmlSerializer serializer = new XmlSerializer(typeof(ModuleDefinitionCollection));
                serializer.Serialize(tw, moduleDefinitions);
                tw.Flush();
            }

            InvalidOperationException exception = Assert.Throws<InvalidOperationException>(() =>
                smartWareApp.WorkItem.ModuleLoader.LoadModules(smartWareApp, configFilePath));

            Assert.That(exception, Is.Not.Null);
            Assert.That(exception.Message, Is.EqualTo("Module [Sample Module] does not have a filepath specified"));
        }
    }
}
